SoftwareConverter
Turns a decoded frame into RGBA, on the CPU.
This is the tier 0 renderer path, and it ships rather than being a placeholder. It is the reference every GPU renderer is checked against, and it is the fallback when a GPU path fails. At 1080p it costs a few milliseconds of CPU per frame, which is too much for comfortable playback and fine for a screenshot, a thumbnail strip or a correctness test.
What it has to get right
Four things, and each one is visible when wrong:
The row pitch. A plane's rows are almost never exactly
widthbytes apart. Assuming they are produces an image that skews diagonally, and it is the most common first bug in a video pipeline. The pitch comes from the frame rather than being computed.The matrix. BT.601 and BT.709 differ enough that using one for the other shifts every hue, worst on saturated reds.
The range. Video is usually studio range, where 16 is black and 235 is white. Treating it as full range turns blacks grey and clips whites.
The bit alignment. A ten bit component sits either in the low ten bits of its word or in the high ten, and the two are sixteen times apart. Guessing produces a picture that is entirely white or entirely black.
Chroma upsampling here is nearest neighbour, which is tier 0's deliberate limit: it is exactly what a GPU renderer does with a nearest-filtered texture, so the two can be compared pixel for pixel. Bilinear chroma is a tier 1 improvement, and it is the point at which the declared chroma location starts to change the picture; see chromaSampleShift for why nearest neighbour does not care.